﻿// <copyright file="NavigationService.cs" company="EffuEfface">
//      Copyright (c) Effu Efface Consulting  All rights reserved.
// </copyright>
// <author>Ryan R. Sites</author>

namespace TVersiPlay.Services
{
    using System;
    using System.Collections.Generic;
    using TVersiPlay.Common.Interfaces;
    using Microsoft.Practices.Unity;
    using Microsoft.Practices.Prism.Regions;
    using TVersiPlay.Common;
    using System.Windows;
    using System.Windows.Threading;

    public class NavigationService : INavigationService
    {
        #region declarations

        private IUnityContainer container;
        private IRegionManager regionManager;

        private Dispatcher dispatcher;

        #endregion //declarations

        #region constructors
        public NavigationService(IUnityContainer container, IRegionManager regionManager)
        {
            this.container = container;
            this.regionManager = regionManager;

            if (Dispatcher.CurrentDispatcher != null)
            {
                this.dispatcher = Dispatcher.CurrentDispatcher;
            }

        }
        #endregion //constructors

        #region properties
        #endregion //properties

        #region methods

        public void NavigateViewToRegion(string viewName, string regionName)
        {

            Action<string, string> navigateAsync = (view, region) =>
           {
               IRegion regionFromRegionName = regionManager.Regions[region];
               IView currentView = null;

               foreach (var v in regionFromRegionName.ActiveViews)
               {
                   currentView = v as IView;
                   break;
               }

               if (regionFromRegionName != null)
               {
                   IView viewToAddToRegion = null;
                   var viewFromRegion = regionFromRegionName.GetView(view);

                   // See if the view already exists in the region. 
                   if (viewFromRegion == null)
                   {
                       try
                       {
                           // the view does not exist yet. Create it and push it into the region
                           viewToAddToRegion = this.container.Resolve<IView>(view);

                           regionFromRegionName.Add(viewToAddToRegion, view, false);

                           regionFromRegionName.Activate(viewToAddToRegion);
                       }
                       catch (Exception ex)
                       {
                           Console.WriteLine(ex.Message.ToString());
                       }

                   }
                   else
                   {
                       // The view already exists. Just show it. 
                       regionFromRegionName.Activate(viewFromRegion);
                   }

                   if (currentView != null && !currentView.PersistView && !currentView.Equals(viewToAddToRegion))
                   {
                       regionFromRegionName.Remove(currentView);
                   }
               }
               else
               {
                   throw new NullReferenceException(string.Format("Could not resolve IRegion from region named {0}", regionName));
               }

           };

            try
            {
                if (!this.dispatcher.CheckAccess())
                    this.dispatcher.BeginInvoke(navigateAsync, DispatcherPriority.Background, viewName, regionName);
                else
                    navigateAsync(viewName, regionName);
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message.ToString());
            }
        }

        public void NavigateViewToRegionAsync(string viewName, string regionName,Action callback)
        {

            Action<string, string> navigateAsync = (view, region) =>
            {
                IRegion regionFromRegionName = regionManager.Regions[region];
                IView currentView = null;

                foreach (var v in regionFromRegionName.ActiveViews)
                {
                    currentView = v as IView;
                    break;
                }

                if (regionFromRegionName != null)
                {
                    IView viewToAddToRegion = null;
                    var viewFromRegion = regionFromRegionName.GetView(view);

                    // See if the view already exists in the region. 
                    if (viewFromRegion == null)
                    {
                        try
                        {
                            // the view does not exist yet. Create it and push it into the region
                            viewToAddToRegion = this.container.Resolve<IView>(view);

                            regionFromRegionName.Add(viewToAddToRegion, view, false);

                            regionFromRegionName.Activate(viewToAddToRegion);
                        }
                        catch (Exception ex)
                        {
                            Console.WriteLine(ex.Message.ToString());
                        }

                    }
                    else
                    {
                        // The view already exists. Just show it. 
                        regionFromRegionName.Activate(viewFromRegion);
                    }                                      

                    if (currentView != null && !currentView.PersistView && !currentView.Equals(viewToAddToRegion))
                    {
                        regionFromRegionName.Remove(currentView);
                    }
                }
                else
                {
                    throw new NullReferenceException(string.Format("Could not resolve IRegion from region named {0}", region));
                }

                if (callback != null)
                    callback();
            };

            try
            {
                if (!this.dispatcher.CheckAccess())
                    this.dispatcher.BeginInvoke(navigateAsync, DispatcherPriority.Background, viewName, regionName);
                else
                    navigateAsync(viewName,regionName);
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message.ToString());
            }           
        }

        #endregion //methods

        #region events
        #endregion //events
       
    }
}
